package com.example.seckill.Controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.seckill.Exception.Enums.RoleEnum;
import com.example.seckill.Exception.ErrorEnum;
import com.example.seckill.Util.MD5Util;
import com.example.seckill.Util.SaltUtil;
import com.example.seckill.annotation.CurrentUser;
import com.example.seckill.common.CommonResult;
import com.example.seckill.mapper.PermissionMapper;
import com.example.seckill.mapper.RoleMapper;
import com.example.seckill.mapper.UserMapper;
import com.example.seckill.mapper.UserRoleMapper;
import com.example.seckill.pojo.User;
import com.example.seckill.pojo.UserRole;
import com.sun.deploy.net.URLEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/user")
public class UserController  {

    @Resource
    UserMapper userMapper;
    @Resource
    RoleMapper roleMapper;
    @Resource
    PermissionMapper permissionMapper;
    @Resource
    UserRoleMapper userRoleMapper;


//    @PostMapping("/login")
//    public CommonResult<?> login(@RequestBody User userParam) {
//        User userPwd = userMapper.selectByName(userParam.getUsername());
//        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("username", userParam.getUsername());
//        queryWrapper.eq("password", userPwd.getPassword());
//        User res = userMapper.selectOne(queryWrapper);
//
//        // 判断密码是否正确
//        if (!bCryptPasswordEncoder.matches(userParam.getPassword(), userPwd.getPassword())) {
//            return CommonResult.error("-1", "密码错误");
//        }
//        if (res == null) {
//            return CommonResult.error("-1", "用户名或密码错误");
//        }
//        HashSet<Permission> permissionSet = new HashSet<>();
//        // 1. 从user_role表通过用户id查询所有的角色信息
//        Integer userId = res.getId();
//        List<UserRole> userRoles = roleMapper.getUserRoleByUserId(userId);
//        // 设置角色id
//        res.setRoles(userRoles.stream().map(UserRole::getRoleId).distinct().collect(Collectors.toList()));
//        for (UserRole userRole : userRoles) {
//            // 2.根据roleId从role_permission表查询出所有的permissionId
//            List<RolePermission> rolePermissions = permissionMapper.getRolePermissionByRoleId(userRole.getRoleId());
//            for (RolePermission rolePermission : rolePermissions) {
//                Integer permissionId = rolePermission.getPermissionId();
//                // 3. 根据permissionId查询permission信息
//                Permission permission = permissionMapper.selectById(permissionId);
//                permissionSet.add(permission);
//            }
//        }
//        // 对资源根据id进行排序
//        LinkedHashSet<Permission> sortedSet = permissionSet.stream().sorted(Comparator.comparing(Permission::getId)).collect(Collectors.toCollection(LinkedHashSet::new));
//        //设置当前用户的资源信息
//        res.setPermissions(sortedSet);
//
//        // 生成token
//        String token = TokenUtils.genToken(res);
//        res.setToken(token);
//        return CommonResult.success(res);
//    }


    @PostMapping("/register")
    public CommonResult<?> register(@RequestBody User user) {
        User res=userMapper.findByUsername(user.getUsername());
        if (res != null) {
            return CommonResult.error(ErrorEnum.REPEAT_USERNAME);
        }
        String salt= SaltUtil.getSalt(8);
        User userInfo = new User();
                user.setUsername(user.getUsername());
                user.setSalt(salt);
                user.setPassword(MD5Util.inputPassToDBPass(user.getPassword(),salt));
                user.setName(user.getName());


        userMapper.insert(userInfo);

        UserRole userRole = UserRole.builder()
                .userId(userInfo.getId())
                .roleId(RoleEnum.USER.getRoleId())
                .build();
        userRoleMapper.insert(userRole);
        return CommonResult.success(user);
    }

//    @PostMapping
//    public CommonResult<?> save(@RequestBody User user) {
//        if (user.getPassword() == null) {
//            user.setPassword(bCryptPasswordEncoder.encode(PwdEnum.PASSWORD.getPassword()));
//        }
//        userMapper.insert(user);
//
//        UserRole userRole = UserRole.builder()
//                .userId(user.getId())
//                .roleId(RoleEnum.USER.getRoleId())
//                .build();
//        userRoleMapper.insert(userRole);
//
//        return CommonResult.success(user);
//    }

    @PutMapping
    public CommonResult<?> update(@RequestBody User user) {
        userMapper.updateById(user);
        return CommonResult.success(user);
    }
//
//    @PutMapping("/pass")
//    public CommonResult<?> pass(@RequestBody Map<String, Object> map) {
//        User user = userMapper.selectById((Integer)map.get("userId"));
//        if (user== null) {
//            return CommonResult.error("-1", "未找到用户");
//        }
//        if (!bCryptPasswordEncoder.matches(map.get("password").toString(), user.getPassword())) {
//            return CommonResult.error("-1", "密码错误");
//        }
//        map.put("newPass", (bCryptPasswordEncoder.encode(map.get("newPass").toString())));
//        userMapper.updatePass(map);
//        return CommonResult.success();
//    }

    // 改变权限接口
    @PutMapping("/changeRole")
    public CommonResult<?> changeRole(@CurrentUser User currentUser, @RequestBody User user) {
        // 先根据角色id删除所有的角色跟权限的绑定关系
        roleMapper.deleteRoleByUserId(Math.toIntExact(user.getId()));
        // 再新增 新的绑定关系
        for (Integer roleId : user.getRoles()) {
            roleMapper.insertUserRole(Math.toIntExact(user.getId()), roleId);
        }


        // 如果当前登录用户的角色列表包含需要修改的角色id，那么就重新登录
        if (user.getId().equals(currentUser.getId())) {
            return CommonResult.success(true);
        }
//        如果不包含，则返回false，不需要重新登录。
        return CommonResult.success(false);
    }

    @DeleteMapping("/{id}")
    public CommonResult<?> update(@PathVariable Long id) {
        userRoleMapper.deleteByUserRoleId(id);
        userMapper.deleteById(id);
        return CommonResult.success(id);
    }

    @GetMapping("/{id}")
    public CommonResult<?> getById(@PathVariable Long id) {
        return CommonResult.success(userMapper.selectById(id));
    }

    @GetMapping("/all")
    public CommonResult<?> findAll() {
        return CommonResult.success(userMapper.selectList(null));
    }
//
//    /**
//     * 统计数据
//     *
//     * @return
//     */
//    @GetMapping("/count")
//    public CommonResult<?> count() {
////        User user = getUser(); // 当前登录的用户信息
//        return CommonResult.success(userMapper.countAddress());
//    }

    /**
     * 用户分页列表查询，包含书籍表的一对多查询
     *
     * @param pageNum
     * @param pageSize
     * @param search
     * @return
     */
    @GetMapping
    public CommonResult<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
                              @RequestParam(defaultValue = "10") Integer pageSize,
                              @RequestParam(defaultValue = "") String search) {
        System.out.println("进入");
        LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery().orderByAsc(User::getId);
//        System.out.println("1.5");
        if (StrUtil.isNotBlank(search)) {
            wrapper.like(User::getUsername, search);
        }

//        System.out.println(2);
        Page<User> userPage = userMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
//        Page<User> userPage = userMapper.findByUsername(new Page<>(pageNum, pageSize), search);
        // 设置用户的角色id列表
        System.out.println("设置角色用户列表");
        for (User record : userPage.getRecords()) {
            List<UserRole> roles = roleMapper.getUserRoleByUserId(Math.toIntExact(record.getId()));
            List<Integer> roleIds = roles.stream().map(UserRole::getRoleId).distinct().collect(Collectors.toList());
            record.setRoles(roleIds);
        }
        System.out.println("成功");
        return CommonResult.success(userPage);
    }

    /**
     * Excel导出
     *

//     * @throws IOException
     */
    @GetMapping("/export")
    public void export(HttpServletResponse response) throws IOException {

        List<Map<String, Object>> list = CollUtil.newArrayList();

        List<User> all = userMapper.selectList(null);
        if(all.isEmpty()) System.out.println("all is Empty");
        else System.out.println("not empty");
        for (User user : all) {
            System.out.println(user.getUsername());
            Map<String, Object> row1 = new LinkedHashMap<>();
            row1.put("用户名", user.getUsername());
            row1.put("名字", user.getName());
            row1.put("性别", user.getGender());
            list.add(row1);
        }
        if(list.isEmpty()) System.out.println("list is empty");

        // 2. 写excel
        ExcelWriter writer = ExcelUtil.getWriter(true);
        writer.write(list, true);

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode("用户信息", "UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");

        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        writer.close();
        IoUtil.close(System.out);
    }

    /**
     * Excel导入
     * 导入的模板可以使用 Excel导出的文件
     *
     * @param file Excel
     * @return
     * @throws IOException
     */
    @PostMapping("/import")
    public CommonResult<?> upload(MultipartFile file) throws IOException {
        InputStream inputStream = file.getInputStream();
        List<List<Object>> lists = ExcelUtil.getReader(inputStream).read(1);
        List<User> saveList = new ArrayList<>();
        String salt=SaltUtil.getSalt(8);
        for (List<Object> row : lists) {
            User user=new User();
            user.setUsername(row.get(0).toString());
            user.setSalt(salt);
            user.setPassword(MD5Util.inputPassToDBPass(MD5Util.inputPassToFromPass(user.getUsername()),salt));
            user.setName(user.getName());
            user.setGender((Integer) row.get(2));
            saveList.add(user);
        }
        for (User user : saveList) {
            userMapper.insert(user);
        }
        return CommonResult.success("上传成功");
    }

}
